import 'dart:io';
import 'package:dart_aliyun_oss/dart_aliyun_oss.dart';
import 'package:path/path.dart' as path;
import 'package:uuid/uuid.dart';

/// 上传进度回调函数类型
typedef UploadProgressCallback = void Function(int sent, int total);

/// 阿里云OSS上传结果
class OSSUploadResult {
  final String? url;
  final String? errorMessage;
  final bool isSuccess;

  OSSUploadResult({
    this.url,
    this.errorMessage,
    required this.isSuccess,
  });

  factory OSSUploadResult.success(String url) {
    return OSSUploadResult(
      url: url,
      isSuccess: true,
    );
  }

  factory OSSUploadResult.error(String errorMessage) {
    return OSSUploadResult(
      errorMessage: errorMessage,
      isSuccess: false,
    );
  }
}

/// 阿里云OSS上传工具类
class AliyunOSSUploader {
  static const String _accessKey = "LTAI5t93Z5Vb3pm53xzoYCrG";
  static const String _secretKey = "2XO766BaYxFFwYrkvjo6dux9vTilQB";
  static const String _bucketName = "gluz-oss";
  static const String _endpoint = "oss-accelerate.aliyuncs.com";
  static const String _domainName = "https://gluz-oss.oss-accelerate.aliyuncs.com";
  static const String _region = "cn-beijing";

  static late final OSSClient _client;
  static bool _isInitialized = false;

  /// 初始化OSS客户端
  static Future<void> _initialize() async {
    if (_isInitialized) return;

    final config = OSSConfig(
      bucketName: _bucketName,
      endpoint: _endpoint,
      region: _region,
      accessKeyIdProvider: () {
        return _accessKey;
    }, accessKeySecretProvider: () {
        return _secretKey;
    }, // 根据您的endpoint设置对应的region
    );

    _client = OSSClient.init(config);
    _isInitialized = true;
  }

  /// 上传文件到OSS
  /// [filePath] 本地文件路径
  /// [folder] 可选，OSS中的文件夹路径，默认为 'uploads'
  /// [fileName] 可选，自定义文件名，默认为原文件名
  /// [onProgress] 可选，上传进度回调函数
  /// 返回上传结果，包含成功后的URL或错误信息
  static Future<OSSUploadResult> uploadFile({
    required String filePath,
    String folder = 'uploads',
    String? fileName,
    UploadProgressCallback? onProgress,
  }) async {
    try {
      // 初始化客户端
      await _initialize();

      // 检查文件是否存在
      final file = File(filePath);
      if (!await file.exists()) {
        return OSSUploadResult.error('文件不存在: $filePath');
      }

      // 获取文件大小
      final fileSize = await file.length();
      
      // 生成文件名
      final originalFileName = path.basename(filePath);
      final extension = path.extension(filePath);
      final finalFileName = fileName ?? '${const Uuid().v4()}$extension';

      // 构建OSS对象键
      final objectKey = '$folder/$finalFileName';

      // 创建进度跟踪器
      int lastReportedProgress = 0;
      
      // 上传文件
      await _client.putObject(
        file,
        objectKey,
          params: OSSRequestParams(
              onSendProgress: (int sent, int total) {
                // 计算进度百分比
                final progress = (sent / total * 100).round();

                // 避免过于频繁的回调，只在进度变化超过1%时才回调
                if (progress > lastReportedProgress || sent == total) {
                  lastReportedProgress = progress;
                  onProgress?.call(sent, total);
                }
              },
          ),
      );

      // 构建访问URL
      final url = '$_domainName/$objectKey';
      return OSSUploadResult.success(url);
    } catch (e) {
      return OSSUploadResult.error('上传异常: $e');
    }
  }

  /// 上传图片文件
  /// [filePath] 本地图片文件路径
  /// [folder] 可选，OSS中的文件夹路径，默认为 'images'
  /// [fileName] 可选，自定义文件名
  /// [onProgress] 可选，上传进度回调函数
  static Future<OSSUploadResult> uploadImage({
    required String filePath,
    String folder = 'images',
    String? fileName,
    UploadProgressCallback? onProgress,
  }) {
    return uploadFile(
      filePath: filePath,
      folder: folder,
      fileName: fileName,
      onProgress: onProgress,
    );
  }

  /// 上传视频文件
  /// [filePath] 本地视频文件路径
  /// [folder] 可选，OSS中的文件夹路径，默认为 'videos'
  /// [fileName] 可选，自定义文件名
  /// [onProgress] 可选，上传进度回调函数
  static Future<OSSUploadResult> uploadVideo({
    required String filePath,
    String folder = 'videos',
    String? fileName,
    UploadProgressCallback? onProgress,
  }) {
    return uploadFile(
      filePath: filePath,
      folder: folder,
      fileName: fileName,
      onProgress: onProgress,
    );
  }

  /// 上传文档文件
  /// [filePath] 本地文档文件路径
  /// [folder] 可选，OSS中的文件夹路径，默认为 'documents'
  /// [fileName] 可选，自定义文件名
  /// [onProgress] 可选，上传进度回调函数
  static Future<OSSUploadResult> uploadDocument({
    required String filePath,
    String folder = 'documents',
    String? fileName,
    UploadProgressCallback? onProgress,
  }) {
    return uploadFile(
      filePath: filePath,
      folder: folder,
      fileName: fileName,
      onProgress: onProgress,
    );
  }

  /// 上传头像文件
  /// [filePath] 本地头像文件路径
  /// [userId] 用户ID，用于构建文件夹路径
  /// [fileName] 可选，自定义文件名
  /// [onProgress] 可选，上传进度回调函数
  static Future<OSSUploadResult> uploadAvatar({
    required String filePath,
    required String userId,
    String? fileName,
    UploadProgressCallback? onProgress,
  }) {
    return uploadFile(
      filePath: filePath,
      folder: 'avatars/$userId',
      fileName: fileName,
      onProgress: onProgress,
    );
  }

  /// 批量上传文件
  /// [filePaths] 本地文件路径列表
  /// [folder] 可选，OSS中的文件夹路径，默认为 'uploads'
  /// [onProgress] 可选，批量上传进度回调函数，参数为当前文件索引和总文件数
  /// 返回所有上传结果
  static Future<List<OSSUploadResult>> uploadFiles({
    required List<String> filePaths,
    String folder = 'uploads',
    void Function(int currentIndex, int totalFiles)? onProgress,
  }) async {
    final results = <OSSUploadResult>[];
    final totalFiles = filePaths.length;
    
    for (int i = 0; i < filePaths.length; i++) {
      final filePath = filePaths[i];
      
      // 报告批量上传进度
      onProgress?.call(i, totalFiles);
      
      final result = await uploadFile(
        filePath: filePath,
        folder: folder,
      );
      results.add(result);
    }
    
    // 报告完成
    onProgress?.call(totalFiles, totalFiles);
    
    return results;
  }

  /// 从URL中提取对象键
  /// [url] OSS文件URL
  static String? extractObjectKey(String url) {
    try {
      final uri = Uri.parse(url);
      final pathSegments = uri.pathSegments;
      if (pathSegments.length >= 2) {
        return pathSegments.skip(1).join('/');
      }
      return null;
    } catch (e) {
      return null;
    }
  }

  /// 检查文件是否已存在于OSS
  /// [objectKey] OSS对象键
  static Future<bool> fileExists(String objectKey) async {
    try {
      await _initialize();
      // 注意：某些版本的SDK可能不支持headObject方法
      // 使用getObject作为替代方案
      await _client.getObject(objectKey);
      return true;
    } catch (e) {
      return false;
    }
  }
}

/// 便捷上传扩展方法
extension OSSUploaderExtension on String {
  /// 上传当前文件路径到OSS
  Future<OSSUploadResult> uploadToOSS({
    String folder = 'uploads',
    String? fileName,
    UploadProgressCallback? onProgress,
  }) {
    return AliyunOSSUploader.uploadFile(
      filePath: this,
      folder: folder,
      fileName: fileName,
      onProgress: onProgress,
    );
  }

  /// 上传当前文件路径作为图片
  Future<OSSUploadResult> uploadAsImage({
    String folder = 'images',
    String? fileName,
    UploadProgressCallback? onProgress,
  }) {
    return AliyunOSSUploader.uploadImage(
      filePath: this,
      folder: folder,
      fileName: fileName,
      onProgress: onProgress,
    );
  }

  /// 上传当前文件路径作为视频
  Future<OSSUploadResult> uploadAsVideo({
    String folder = 'videos',
    String? fileName,
    UploadProgressCallback? onProgress,
  }) {
    return AliyunOSSUploader.uploadVideo(
      filePath: this,
      folder: folder,
      fileName: fileName,
      onProgress: onProgress,
    );
  }

  /// 上传当前文件路径作为文档
  Future<OSSUploadResult> uploadAsDocument({
    String folder = 'documents',
    String? fileName,
    UploadProgressCallback? onProgress,
  }) {
    return AliyunOSSUploader.uploadDocument(
      filePath: this,
      folder: folder,
      fileName: fileName,
      onProgress: onProgress,
    );
  }
}
